import DialogStore from ".";
import { action, observable, computed, toJS } from 'mobx';
import { Button, message, Modal  } from 'antd';
import { loadDataSource, loadTables, currentDataSouece, getTableFields, saveDataSet, loadPageDs, getDataSet, nativeFields, loadCondition, deleteDataSet } from "../../apis/dataset";
import { SYS_LOCAL_POOLNAME } from "../../constants/dataset";
import { dndTargets, joinTypes } from "../../constants";
import { WeaLocaleProvider } from "ecCom";
import { clearCondition } from "../monitor/action";
const getLabel = WeaLocaleProvider.getLabel;

export default class DataSourceDialogStore extends DialogStore {
    @observable name = '';
    @observable dsType = "0";
    @observable dataSource = [];
    @observable selectedDataSource = SYS_LOCAL_POOLNAME;
    @observable dbTables = [];
    @observable quickSearchValue = '';
    @observable tableLoading = false;
    @observable heihgt = 0;
    @observable currentDataSource;
    @observable dmTables = []; // 数据模型中join的表(工作区内的表)
    @observable treeData = []; // 数据模型中join的表 - 符合树的数据

    @observable fieldsCache = {};

    @observable relatedCardVisible = false;

    @observable dsLoading = false;
    @observable dsSelectionVisible = false;
    nameError;

    @observable pageName = "";
    @observable nativeFields = [];
    @observable conditionLeft;
    @observable conditionRight;
    @observable conditionList = [{ key: -1 }];
    @observable relatedLayout;
    @observable dsMenuVisible = false;

    constructor() {
        super();
        this.style = {};
        // this.buttons = [<Button onClick={this.onSave} type="primary">{getLabel(30986, '保存')}</Button>,
        // <Button onClick={this.hide} type="primary">{getLabel('31129', '取消')}</Button>]
    }

    @computed get tables() {
        return this.quickSearchValue ? this.dbTables.filter(d => d.text.indexOf(this.quickSearchValue) > -1 || d.name.indexOf(this.quickSearchValue) > -1)
            : this.dbTables;
    }

    @computed get fieldOptions() {
        const options = [];
        this.dmTables.forEach(table => {
            const { name, text } = table;
            table.fields.forEach(d => {
                options.push({
                    key: `${name}.${d.name}`,
                    showname: `${text}.${d.text}`
                });
            });
        });
        return options;
    }

    @action loadNativeFields = () => {
        nativeFields(this.pageid).then(fields => {
            const options = [];
            fields.forEach(d => {
                const { key, showname, children } = d;
                children.forEach(f => {
                    options.push({
                        showname: `${showname}.${f.showname}`,
                        key: `${key}.${f.key}`
                    });
                });
            });
            this.nativeFields = options;
        });
    }

    @action loadCondition=()=>{
        loadCondition(this.id).then(data=>{
            this.conditionList = data;
        });
    }

    @action changeConditionLeft = (condition, value) => {
        this.conditionList = this.conditionList.map(d => {
            if (d.key === condition.key) {
                return {
                    ...d,
                    left: value
                }
            } else {
                return { ...d };
            }
        });
    }
    @action changeConditionRight = (condition, value) => {
        this.conditionList = this.conditionList.map(d => {
            if (d.key === condition.key) {
                return {
                    ...d,
                    right: value
                }
            } else {
                return { ...d };
            }
        });
    }
    get minKey() {
        return Math.min(...this.conditionList.filter(d => typeof d.key === 'number').map(d => d.key)) - 1;
    }
    @action addCondition = () => {
        this.conditionList.push({
            left: '',
            right: '',
            key: this.minKey
        })
    }
    @action deleteCondition(condition) {
        this.conditionList = this.conditionList.filter(d => d.key !== condition.key);
    }
    @action clearCondition = () => {
        this.conditionList = [{ key: -1 }];
    }

    @action showDataSourceSelection = () => {
        this.dsLoading = true;
        this.dsSelectionVisible = true;
        this.loadDataSource();
        document.addEventListener('click', this.hideDataSourceSelction);
    }
    @action hideDataSourceSelction = () => {
        this.dsSelectionVisible = false;
        document.removeEventListener('click', this.hideDataSourceSelction);
    }
    @action changeDataSource = (dsKey) => {
        if (dsKey !== this.selectedDataSource) {
            this.dmTables = [];
            this.fieldsCache = {};
            this.treeData = [];
        }
        this.selectedDataSource = dsKey;
        this.loadCurrentDataSource(dsKey);
        this.loadTables();
    }
    @action changeName = (name) => {
        this.name = name;
    }

    @action onSave = () => {
        if (!this.name) {
            this.nameError.showError();
            return;
        }
        if (this.dmTables.length === 0) {
            message.error(getLabel('502892', '请从左侧拖拽表、视图'));
            return;
        }
        const relatedFieldsList = [];
        const getTable = (d) => {
            console.log(d,d.relatedFields.length,"d.relatedFields");
            const relatedFields = d.relatedFields;
            const len = relatedFields.length;
            for(let i = 0 ; i < len; i++) {
                if(relatedFields[i][0] || relatedFields[i][1]) {
    
                    relatedFieldsList.push(relatedFields[i]);
                }
                
            }
            const rt = {
                id: d.id,
                name: d.name,
                refTable: d.refTable,
                joinType: d.joinType,
                text: d.text,
                tableType: d.tableType,
                children: d.children.map(getTable),
                relatedFields: d.relatedFields,
                uuid : d.uuid || ""
            };
            return rt;
        }
        const datas = this.treeData.map(getTable);
        
        let needBreak = false;
        console.log(datas,datas[0].children,"children")
        if(datas[0].children && datas[0].children.length > 0) {
            if(relatedFieldsList.length == 0) {
                message.error(getLabel('513477','未选择关联方式'));
                return false;
            } else {
                const childrens =  datas[0].children;
                for(let i = 0 ; i < childrens.length ; i++) {
                    const rf = childrens[i].relatedFields;
                    if(rf.length == 0) {
                        message.error(getLabel('513477','未选择关联方式'));
                        return false;
                    } else {
                        let hasRelated = false;
                        for(let j = 0 ; j < rf.length ; j++) {
                            const related = rf[j];
                            if(related[0] && related[1]) {
                                hasRelated = true;
                            } else if(related[0] || related[1]) {
                                message.error(getLabel('513481','左右侧关联方式不能为空'));
                                needBreak = true;
                                return false;
                            }
                        }
                        if(!hasRelated) {
                            message.error(getLabel('513477','未选择关联方式'));
                            needBreak = true;
                            return false;
                        }
                    }
                    console.log(needBreak)
                    if(needBreak)
                        return false;
                }

                // for(let i = 0 ; i < relatedFieldsList.length ; i++) {
                //     if(relatedFieldsList[i][0] && relatedFieldsList[i][1]) {
    
                //     } else {
                //         message.error(getLabel('513481','左右侧关联方式不能为空'));
                //         return false;
                //     }
                // }
            }
        }
        
        saveDataSet({
            pageid: this.pageid,
            id: this.id,
            name: this.name,
            dataSource: this.selectedDataSource,
            datas: JSON.stringify(datas)
        }).then(() => {
            this.hide();
            message.success(getLabel('502231','保存成功'));
            if (this.reloadPageDsList) {
                this.reloadPageDsList();
            }
        })

    }

    @action newDataSource = (pageid, pageName) => {
        if (!pageid) {
            message.error(getLabel('508649', '请先保存EXCEL，再创建数据源'));
            return;
        }
        this.pageid = pageid;
        this.pageName = pageName;
        this.title = getLabel('503305', '新建数据集合');
        this.buttons = this.getButtons();
        this.id = "";
        this.name = "";
        this.dsMenuVisible = false;
        this.open();
        const clientWidth = document.documentElement.clientWidth - 200;
        const clientHeight = document.documentElement.clientHeight - 100;
        this.style.width = clientWidth;
        this.heihgt = clientHeight;
        this.dmTables = [];
        this.treeData = [];
        this.clearCondition();
        this.loadCurrentDataSource();
        this.loadTables();
        this.loadNativeFields();
    }

    @action openDataSource = (pageid, pageName, uuid) => {
        this.pageid = pageid;
        this.pageName = pageName;
        this.id = uuid;
        this.title = getLabel('503306', '数据集合') + ":";
        this.buttons = this.getButtons();
        this.dsMenuVisible = false;
        this.open();
        const clientWidth = document.documentElement.clientWidth - 200;
        const clientHeight = document.documentElement.clientHeight - 100;
        this.style.width = clientWidth;
        this.style.width = clientWidth;
        this.heihgt = clientHeight;
        this.dmTables = [];
        this.treeData = [];
        this.clearCondition();
        getDataSet(uuid).then(this.setDataSet);
        this.loadNativeFields();;
        // this.loadCondition();
    }

    @action setDataSet = (ds) => {
        const { name, dataSource, tables } = ds;
        this.title = `${getLabel('503306', '数据集合') + ":" + name}`;
        this.name = name;
        this.selectedDataSource = dataSource;
        this.loadCurrentDataSource(dataSource);
        this.loadTables();
        this.dmTables = tables;
        this.treeData = this.transferToTreeData(this.dmTables);
    }

    @action loadCurrentDataSource = (id) => {
        currentDataSouece(id).then(action(data => {
            this.currentDataSource = data;
            this.selectedDataSource = data.key;
        }));
    }
    @action loadDataSource = () => {
        loadDataSource().then(action(datas => {
            this.dataSource = datas;
            this.dsLoading = false;
        }));
    }

    @action loadTables = () => {
        this.tableLoading = true;
        loadTables(this.selectedDataSource).then(datas => {
            this.dbTables = datas;
            this.tableLoading = false;
        });
    }
    @action onTableRemove = (node, didDrop) => {
        if (didDrop) return;
        const names = [];
        this.dmTables = this.dmTables.filter(t => {
            const canRemove = t.id === node.id || t.id.indexOf(node.id) === 0;
            if (canRemove) {
                names.push(t.name)
            }
            return !canRemove;
        });
        this.treeData = this.transferToTreeData(this.dmTables);
        this.canDarg(names, true);
    }
    @action onNodeOptClick = node => {
        if (node.fields && node.parentNode.fields) return;
        this.getTableFields(node.name, node.parentNode.name)
            .then(([nfields, pfields]) => {
                this.dmTables.forEach(t => {
                    if (t.name === node.name) {
                        t.fields = nfields;
                    } else if (t.name === node.parentNode.name) {
                        t.fields = pfields;
                    }
                    return t;
                });
                this.treeData = this.transferToTreeData(this.dmTables);
            });
    }

    @action onRelatedFieldsChange = (nodeName, relatedFields) => {
        this.onNodeChange(nodeName, 'relatedFields', relatedFields);
    }

    @action onJoinTypeChange = (nodeName, joinType) => {
        this.onNodeChange(nodeName, 'joinType', joinType);
    }
    @action onNodeChange = (nodeName, key, value) => {
        const node = this.dmTables.find(t => t.name === nodeName);
        node[key] = value;
        this.treeData = this.transferToTreeData(this.dmTables);
    }
    @action onTableAdd = (source, target, targetType) => {
        const isWorkSpace = targetType === dndTargets.WORKSPACE;

        // 拖拽到工作区 默认添加至根节点
        if (isWorkSpace && this.dmTables.length) {
            target = this.treeData[0];
        }

        const { id: sId, name: sname } = source;
        const { id: tId, name: tname } = target;

        // 相同节点不能移动
        if (tname === sname) return;

        // 父节点不能移动到子节点后
        if (sId && sId.length < tId.length) return;

        this.getTableFields(sname, tname)
            .then(action(([sfields, tfields]) => {
                const relatedFields = [[]];
                const relVisible = !!tname;
                if (sId) {// 工作区之间的表移动 -> update
                    this.dmTables.forEach(t => {
                        if (t.id === source.id) {
                            t.fields = sfields;
                            t.refTable = tname;
                            t.relVisible = relVisible;
                            t.joinType = joinTypes.LEFT;
                            t.relatedFields = relatedFields;
                        } else if (t.id === tId) {
                            t.fields = tfields;
                        }
                    });
                } else { // 表列表拖到工作区 -> 新增
                    let id;
                    if (tId) {
                        id = `${tId}_${target.children.length}`;
                        const ttable = this.dmTables.find(t => t.name === tname);
                        if (!ttable.fields) {
                            ttable.fields = tfields;
                        }
                    } else {
                        id = '0';
                    }
                    this.dmTables.push({
                        ...source,
                        id,
                        relVisible,
                        relatedFields,
                        fields: sfields,
                        refTable: tname,
                        children: [],
                        joinType: joinTypes.INNER
                    });
                    this.canDarg([source.name], false);
                }
                this.treeData = this.transferToTreeData(this.dmTables);
            }));

    }

    @action canDarg = (tableNames, canDarg) => {
        const tables = toJS(this.tables);

        tables.forEach(t => {
            if (tableNames.includes(t.name)) {
                t.draggable = canDarg;
            }
        });

        this.dbTables = tables;
    }
    @action transferToTreeData = (dmTables) => {
        if (!dmTables.length) return dmTables;
        const rootNode = dmTables.find(t => !t.refTable);
        const _children = parentNode => {
            if (!parentNode) return;
            return dmTables.filter(t => {
                const ischild = t.refTable === parentNode.name;

                if (ischild) {
                    t.parentNode = parentNode;
                    t.children = _children(t);
                }

                return ischild;
            });
        };
        const _id = parentNode => {
            const id = parentNode.id;

            parentNode.children.forEach((n, i) => {
                n.id = `${id}_${i}`;
                _id(n);
            });
        };

        rootNode.id = '0';
        rootNode.children = _children(rootNode);

        _id(rootNode);

        return [rootNode];
    }
    @action getTableFields = (...tableNames) => {
        const dsName = this.currentDataSource.key;
        return Promise.all(tableNames.filter(n => n).map(name => new Promise(resolve => {
            const fields = this.fieldsCache[name];
            if (fields) {
                resolve(fields);
            } else {
                getTableFields(dsName, name).then((data) => {
                    this.fieldsCache[name] = data;
                    resolve(data);
                });
            }
        })));
    }

    @action onRelatedCardVisibleChange = (visible) => {
        this.relatedCardVisible = visible;
    }

    @action dsShowMenu = (visible) => {
        this.dsMenuVisible = visible;
    }

    @action deleteDataSource = (uuid) => {
        Modal.confirm({
            content: getLabel('505984', '是否确认删除？'),
            onOk: () => {
                deleteDataSet(uuid).then((data) => {
                    this.hide();
                    if(data.sign === '1'){
                        message.success(data.message);
                    } else {
                        message.error(data.message);
                    }
                    if (this.reloadPageDsList) {
                        this.reloadPageDsList();
                    }
                });
            },
            onCancel() { },
        });
    }

    @action getButtons = () => {
        const buttons = [<Button ecId={`${this && this.props && this.props.ecId || ''}_Button@zc62vz@save`} onClick={this.onSave} type="primary">{getLabel(30986, '保存')}</Button>,
        <Button ecId={`${this && this.props && this.props.ecId || ''}_Button@000awk@cancel`} onClick={this.hide} type="primary">{getLabel('31129', '取消')}</Button>];
        return buttons;
   }
}